package com.gzhryc.shared_device.oem.code.statistics.services;

import com.gzhryc.common.DateTools;
import com.gzhryc.common.StringTools;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.Conditions;
import com.gzhryc.jdbc.MultiDBTools;
import com.gzhryc.shared_device.common.CountryAreaUtils;
import com.gzhryc.shared_device.common.device.services.DeviceService;
import com.gzhryc.shared_device.common.device.services.dto.DeviceSearch;
import com.gzhryc.shared_device.oem.code.place.services.PlacePhysicalStoreService;
import com.gzhryc.shared_device.oem.code.statistics.dao.CityAreaDayStatisticsDao;
import com.gzhryc.shared_device.oem.code.statistics.dao.db.CityAreaDayStatistics;
import com.gzhryc.shared_device.oem.code.statistics.dao.models.ProvinceSumMoneyData;
import org.apache.commons.lang3.time.DateFormatUtils;

import java.sql.SQLException;
import java.util.Date;
import java.util.List;

public class CityAreaDayStatisticsService {

    static Logger log = Logger.getLogger(CityAreaDayStatisticsService.class);

    public static CityAreaDayStatisticsService self() {
        return MultiDBTools.getService(CityAreaDayStatisticsService.class, true);
    }

    public static CityAreaDayStatisticsService self(String jdbcKey) {
        return MultiDBTools.getService(jdbcKey, CityAreaDayStatisticsService.class, true);
    }

    CityAreaDayStatisticsDao dao;

    public CityAreaDayStatisticsService(String jdbcKey) {
        dao = new CityAreaDayStatisticsDao(jdbcKey);
    }

    public CityAreaDayStatistics getOrAddByKeys(String areaCode, Date createDate){
        if(StringTools.isNotBlank(areaCode) && createDate != null){
            String dayDate = DateFormatUtils.format(createDate,"yyyyMMdd");
            Conditions conditions = new Conditions(CityAreaDayStatistics.class);
            conditions.and().is("areaCode",areaCode);
            conditions.and().is("dayDate",dayDate);
            try {
                CityAreaDayStatistics statistics = dao.get(conditions);
                if(statistics != null){
                    return statistics;
                }else{
                    Long placeCount = PlacePhysicalStoreService.self().countByAreaCode(areaCode);
                    if(placeCount == null){
                        placeCount = 0L;
                    }

                    DeviceSearch deviceSearch = new DeviceSearch();
                    deviceSearch.setAreaCode(areaCode);
                    Long deviceCount = DeviceService.self().countBySearch(deviceSearch);
                    if(deviceCount == null){
                        deviceCount = 0L;
                    }
                    String[] areaNames = CountryAreaUtils.getAreaNames(areaCode.split(","));
                    Integer yearNum = Integer.valueOf(DateFormatUtils.format(createDate, "yyyy"));
                    Integer monthNum = Integer.valueOf(DateFormatUtils.format(createDate, "MM"));
                    Integer dayNum = Integer.valueOf(DateFormatUtils.format(createDate, "dd"));
                    statistics = new CityAreaDayStatistics();
                    statistics.setAreaCode(areaCode);
                    statistics.setDayDate(dayDate);
                    statistics.setProvince(areaNames[0]);
                    statistics.setCity(areaNames[1]);
                    statistics.setCityArea(areaNames[2]);
                    statistics.setYearNum(yearNum);
                    statistics.setMonthNum(monthNum);
                    statistics.setDayNum(dayNum);
                    statistics.setMaxPlaceCount(placeCount.intValue());
                    statistics.setMaxDeviceCount(deviceCount.intValue());
                    statistics.setCreateDate(createDate);

                    if(dao.insert(statistics) > 0){
                        return statistics;
                    }
                }
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }
        return null;
    }

    public List<ProvinceSumMoneyData> sumMoneyGroupProvince(Date startDate, Date endDate){
        if(startDate != null && endDate != null) {
            Conditions conditions = new Conditions(CityAreaDayStatistics.class);
            conditions.and().ge("createDate",startDate);
            conditions.and().le("createDate",endDate);

            try {
                return dao.sumMoneyGroupProvince(conditions);
            } catch (SQLException e) {
                log.info(e.getMessage(),e);
            }
        }
        return null;
    }

    public void addOneOrderData(String areaCode,Date createDate,Long orderMoney,Long orderPayMoney){
        CityAreaDayStatistics statistics = getOrAddByKeys(areaCode,createDate);
        if(statistics != null){
            Conditions conditions = new Conditions(CityAreaDayStatistics.class);
            conditions.and().is("areaCode",areaCode);
            conditions.and().is("dayDate",statistics.getDayDate());

            CityAreaDayStatistics updateEntity = new CityAreaDayStatistics();
            updateEntity.setOrderCount(1);
            updateEntity.setOrderMoney(orderMoney);
            updateEntity.setOrderPayMoney(orderPayMoney);

            try {
                if(dao.updateNotNullAndInc(updateEntity,conditions,"orderCount","orderMoney","orderPayMoney") <= 0){
                    log.error("修改城区统计(支付)失败，区域：{{0}}，时间：{{1}}",areaCode,createDate);
                }
            } catch (SQLException e) {
                log.error(e.getMessage(),e);
            }
        }else{
            log.error("未找到或创建城区统计，区域：{{0}}，时间：{{1}}",areaCode,createDate);
        }
    }

    public void addOneCancelData(String areaCode,Date refundDate,Long cancelMoney,Date finishDate){
        CityAreaDayStatistics statistics = getOrAddByKeys(areaCode,refundDate);
        if(statistics != null){
            Conditions conditions = new Conditions(CityAreaDayStatistics.class);
            conditions.and().is("areaCode",areaCode);
            conditions.and().is("dayDate", statistics.getDayDate());

            //同一天则需要修改支付金额
            if (DateTools.isSameDay(refundDate, finishDate)) {
                CityAreaDayStatistics updateEntity = new CityAreaDayStatistics();
                updateEntity.setCancelOrderCount(1);
                updateEntity.setCancelOrderMoney(cancelMoney);

                try {
                    if (dao.updateNotNullAndInc(updateEntity, conditions, "cancelOrderCount", "cancelOrderMoney") > 0) {
                        updateEntity = new CityAreaDayStatistics();
                        updateEntity.setOrderPayMoney(cancelMoney);
                        dao.updateNotNullAndReduce(updateEntity, conditions, "orderPayMoney");
                    }else{
                        log.error("修改城区统计(撤销)失败，区域：{{0}}，时间：{{1}}", areaCode, refundDate);
                    }
                } catch (SQLException e) {
                    log.error(e.getMessage(), e);
                }
            }else{
                CityAreaDayStatistics updateEntity = new CityAreaDayStatistics();
                updateEntity.setHistoryCancelOrderCount(1);
                updateEntity.setHistoryCancelOrderMoney(cancelMoney);

                try {
                    if (dao.updateNotNullAndInc(updateEntity, conditions, "historyCancelOrderCount", "historyCancelOrderMoney") <= 0) {
                        log.error("修改城区统计(历史撤销)失败，时间：{{0}}", refundDate);
                    }
                } catch (SQLException e) {
                    log.error(e.getMessage(), e);
                }
            }
        } else {
            log.error("未找到或创建区域统计，撤销统计失败，区域：{{0}}，时间：{{1}}", areaCode, refundDate);
        }
    }

    public void addOneRefundData(String areaCode,Date refundDate,Long refundMoney,Date finishDate){
        CityAreaDayStatistics statistics = getOrAddByKeys(areaCode,refundDate);
        if(statistics != null){
            Conditions conditions = new Conditions(CityAreaDayStatistics.class);
            conditions.and().is("areaCode",areaCode);
            conditions.and().is("dayDate", statistics.getDayDate());

            //同一天则需要修改支付金额
            if (DateTools.isSameDay(refundDate, finishDate)) {
                CityAreaDayStatistics updateEntity = new CityAreaDayStatistics();
                updateEntity.setOrderPayMoney(refundMoney);

                try {
                    if (dao.updateNotNullAndReduce(updateEntity, conditions, "orderPayMoney") <= 0) {
                        log.error("修改城区统计(退款)失败，区域：{{0}}，时间：{{1}}", areaCode, refundDate);
                    }
                } catch (SQLException e) {
                    log.error(e.getMessage(), e);
                }
            }else{
                CityAreaDayStatistics updateEntity = new CityAreaDayStatistics();
                updateEntity.setHistoryRefundOrderCount(1);
                updateEntity.setHistoryRefundOrderMoney(refundMoney);

                try {
                    if (dao.updateNotNullAndInc(updateEntity, conditions, "historyRefundOrderCount", "historyRefundOrderMoney") <= 0) {
                        log.error("修改城区统计(历史退款)失败，时间：{{0}}", refundDate);
                    }
                } catch (SQLException e) {
                    log.error(e.getMessage(), e);
                }
            }
        } else {
            log.error("未找到或创建区域统计，退款统计失败，区域：{{0}}，时间：{{1}}", areaCode, refundDate);
        }
    }
}
